home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 21
/
Cream of the Crop 21 (Terry Blount) (October 1996).iso
/
os2
/
e33el2.zip
/
emacs
/
19.33
/
lisp
/
solar.el
< prev
next >
Wrap
Lisp/Scheme
|
1996-05-23
|
45KB
|
1,046 lines
;;; solar.el --- calendar functions for solar events.
;; Copyright (C) 1992, 1993, 1995 Free Software Foundation, Inc.
;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
;; Denis B. Roegel <Denis.Roegel@loria.fr>
;; Keywords: calendar
;; Human-Keywords: sunrise, sunset, equinox, solstice, calendar, diary,
;; holidays
;; This file is part of GNU Emacs.
;; GNU Emacs is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to the
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;;; Commentary:
;; This collection of functions implements the features of calendar.el,
;; diary.el, and holiday.el that deal with times of day, sunrise/sunset, and
;; equinoxes/solstices.
;; Based on the ``Almanac for Computers 1984,'' prepared by the Nautical
;; Almanac Office, United States Naval Observatory, Washington, 1984, on
;; ``Astronomical Formulae for Calculators,'' 3rd ed., by Jean Meeus,
;; Willmann-Bell, Inc., 1985, on ``Astronomical Algorithms'' by Jean Meeus,
;; Willmann-Bell, Inc., 1991, and on ``Planetary Programs and Tables from
;; -4000 to +2800'' by Pierre Bretagnon and Jean-Louis Simon, Willmann-Bell,
;; Inc., 1986.
;;
;; Accuracy:
;; 1. Sunrise/sunset times will be accurate to the minute for years
;; 1951--2050. For other years the times will be within +/- 2 minutes.
;;
;; 2. Equinox/solstice times will be accurate to the minute for years
;; 1951--2050. For other years the times will be within +/- 1 minute.
;; Comments, corrections, and improvements should be sent to
;; Edward M. Reingold Department of Computer Science
;; (217) 333-6733 University of Illinois at Urbana-Champaign
;; reingold@cs.uiuc.edu 1304 West Springfield Avenue
;; Urbana, Illinois 61801
;;; Code:
(if (fboundp 'atan)
(require 'lisp-float-type)
(error "Solar/lunar calculations impossible since floating point is unavailable."))
(require 'cal-dst)
(require 'cal-julian)
;;;###autoload
(defvar calendar-time-display-form
'(12-hours ":" minutes am-pm
(if time-zone " (") time-zone (if time-zone ")"))
"*The pseudo-pattern that governs the way a time of day is formatted.
A pseudo-pattern is a list of expressions that can involve the keywords
`12-hours', `24-hours', and `minutes', all numbers in string form,
and `am-pm' and `time-zone', both alphabetic strings.
For example, the form
'(24-hours \":\" minutes
(if time-zone \" (\") time-zone (if time-zone \")\"))
would give military-style times like `21:07 (UTC)'.")
;;;###autoload
(defvar calendar-latitude nil
"*Latitude of `calendar-location-name' in degrees.
The value can be either a decimal fraction (one place of accuracy is
sufficient), + north, - south, such as 40.7 for New York City, or the value
can be a vector [degrees minutes north/south] such as [40 50 north] for New
York City.
This variable should be set in `site-start'.el.")
;;;###autoload
(defvar calendar-longitude nil
"*Longitude of `calendar-location-name' in degrees.
The value can be either a decimal fraction (one place of accuracy is
sufficient), + east, - west, such as -73.9 for New York City, or the value
can be a vector [degrees minutes east/west] such as [73 55 west] for New
York City.
This variable should be set in `site-start'.el.")
(defsubst calendar-latitude ()
"Convert calendar-latitude to a signed decimal fraction, if needed."
(if (numberp calendar-latitude)
calendar-latitude
(let ((lat (+ (aref calendar-latitude 0)
(/ (aref calendar-latitude 1) 60.0))))
(if (equal (aref calendar-latitude 2) 'north)
lat
(- lat)))))
(defsubst calendar-longitude ()
"Convert calendar-longitude to a signed decimal fraction, if needed."
(if (numberp calendar-longitude)
calendar-longitude
(let ((long (+ (aref calendar-longitude 0)
(/ (aref calendar-longitude 1) 60.0))))
(if (equal (aref calendar-longitude 2) 'east)
long
(- long)))))
;;;###autoload
(defvar calendar-location-name
'(let ((float-output-format "%.1f"))
(format "%s%s, %s%s"
(if (numberp calendar-latitude)
(abs calendar-latitude)
(+ (aref calendar-latitude 0)
(/ (aref calendar-latitude 1) 60.0)))
(if (numberp calendar-latitude)
(if (> calendar-latitude 0) "N" "S")
(if (equal (aref calendar-latitude 2) 'north) "N" "S"))
(if (numberp calendar-longitude)
(abs calendar-longitude)
(+ (aref calendar-longitude 0)
(/ (aref calendar-longitude 1) 60.0)))
(if (numberp calendar-longitude)
(if (> calendar-longitude 0) "E" "W")
(if (equal (aref calendar-longitude 2) 'east) "E" "W"))))
"*Expression evaluating to name of `calendar-longitude', calendar-latitude'.
For example, \"New York City\". Default value is just the latitude, longitude
pair.
This variable should be set in `site-start'.el.")
(defvar solar-error 0.5
"*Tolerance (in minutes) for sunrise/sunset calculations.
A larger value makes the calculations for sunrise/sunset faster, but less
accurate. The default is half a minute (30 seconds), so that sunrise/sunset
times will be correct to the minute.
It is useless to set the value smaller than 4*delta, where delta is the
accuracy in the longitude of the sun (given by the function
`solar-ecliptic-coordinates') in degrees since (delta/360) x (86400/60) = 4 x
delta. At present, delta = 0.01 degrees, so the value of the variable
`solar-error' should be at least 0.04 minutes (about 2.5 seconds).")
(defvar solar-n-hemi-seasons
'("Vernal Equinox" "Summer Solstice" "Autumnal Equinox" "Winter Solstice")
"List of season changes for the northern hemisphere.")
(defvar solar-s-hemi-seasons
'("Autumnal Equinox" "Winter Solstice" "Vernal Equinox" "Summer Solstice")
"List of season changes for the southern hemisphere.")
(defvar solar-sidereal-time-greenwich-midnight
nil
"Sidereal time at Greenwich at midnight (universal time).")
(defvar solar-spring-or-summer-season nil
"T if spring or summer and nil otherwise.
Needed for polar areas, in order to know whether the day lasts 0 or 24 hours.")
(defun solar-setup ()
"Prompt user for latitude, longitude, and time zone."
(beep)
(if (not calendar-longitude)
(setq calendar-longitude
(solar-get-number
"Enter longitude (decimal fraction; + east, - west): ")))
(if (not calendar-latitude)
(setq calendar-latitude
(solar-get-number
"Enter latitude (decimal fraction; + north, - south): ")))
(if (not calendar-time-zone)
(setq calendar-time-zone
(solar-get-number
"Enter difference from Coordinated Universal Time (in minutes): "))))
(defun solar-get-number (prompt)
"Return a number from the minibuffer, prompting with PROMPT.
Returns nil if nothing was entered."
(let ((x (read-string prompt "")))
(if (not (string-equal x ""))
(string-to-int x))))
;; The condition-case stuff is needed to catch bogus arithmetic
;; exceptions that occur on some machines (like Sparcs)
(defun solar-sin-degrees (x)
(condition-case nil
(sin (degrees-to-radians (mod x 360.0)))
(solar-sin-degrees x)))
(defun solar-cosine-de